// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

// 引入必要的命名空间
// 引入iPanel.Otlp.Model.MetricValues命名空间，用于处理度量值相关的模型
using iPanel.DataProvider;
using iPanel.Model.Otlp;
using iPanel.Otlp.Model.MetricValues;
// 引入Google.Protobuf.Collections命名空间，用于处理Protobuf集合
using Google.Protobuf.Collections;
using OpenTelemetry.Proto.Collector.Resources.V1;


// 引入OpenTelemetry.Proto.Common.V1命名空间，包含OpenTelemetry通用协议的定义
using OpenTelemetry.Proto.Common.V1;
// 引入OpenTelemetry.Proto.Logs.V1命名空间，包含OpenTelemetry日志协议的定义
using OpenTelemetry.Proto.Logs.V1;
// 引入OpenTelemetry.Proto.Metrics.V1命名空间，包含OpenTelemetry度量协议的定义
using OpenTelemetry.Proto.Metrics.V1;
// 引入OpenTelemetry.Proto.Trace.V1命名空间，包含OpenTelemetry跟踪协议的定义
using OpenTelemetry.Proto.Trace.V1;
using SqlSugar;

// 引入System.Collections.Concurrent命名空间，提供并发集合类
using System.Collections.Concurrent;

// 引入System.Text命名空间，用于处理文本和字符串操作
using System.Text;


// 引入OpenTelemetry.Proto.Trace.V1.Span.Types的静态成员，方便使用Span相关类型
using static OpenTelemetry.Proto.Trace.V1.Span.Types;

// 将OpenTelemetry.Proto.Resource.V1.Resource重命名为Resource，方便使用
using Resource = OpenTelemetry.Proto.Resource.V1.Resource;
// 将OpenTelemetry.Proto.Trace.V1.Status重命名为Status，方便使用
using Status = OpenTelemetry.Proto.Trace.V1.Status;

namespace iPanel.Otlp.Storage;

/// <summary>
/// 该类用于管理遥测数据的存储和检索，包括应用程序、日志、指标和跟踪数据。
/// </summary>
public sealed class TelemetryRepository
{
    /// <summary>
    /// 暂停管理器，用于控制数据添加操作的暂停状态。
    /// </summary>
    private readonly PauseManager _pauseManager;
    private readonly TelemetryDbContext telemetryDbContext;
    private readonly OtlpConsoleLogService otlpConsoleLogService;

    /// <summary>
    /// 日志记录器，用于记录操作过程中的信息和错误。
    /// </summary>
    private readonly ILogger _logger;

    /// <summary>
    /// 用于线程同步的锁对象。
    /// </summary>
    private readonly object _lock = new();

    /// <summary>
    /// 订阅执行的最小时间间隔，避免频繁触发订阅回调。
    /// </summary>
    internal TimeSpan _subscriptionMinExecuteInterval = TimeSpan.FromSeconds(10);

    /// <summary>
    /// 应用程序相关的订阅列表，当有新的应用程序信息时触发。
    /// </summary>
    private readonly List<Subscription> _applicationSubscriptions = new();

    /// <summary>
    /// 日志相关的订阅列表，当有新的日志信息时触发。
    /// </summary>
    private readonly List<Subscription> _logSubscriptions = new();

    /// <summary>
    /// 指标相关的订阅列表，当有新的指标信息时触发。
    /// </summary>
    private readonly List<Subscription> _metricsSubscriptions = new();

    /// <summary>
    /// 跟踪相关的订阅列表，当有新的跟踪信息时触发。
    /// </summary>
    private readonly List<Subscription> _tracesSubscriptions = new();

    /// <summary>
    /// 资源变化更新
    /// </summary>
    private readonly List<Action<OtlpResourceView>> _resourceSubscriptions = new();

    /// <summary>
    /// 存储应用程序信息的并发字典，键为应用程序键，值为OtlpApplication对象。
    /// </summary>
    private readonly ConcurrentDictionary<ApplicationKey, OtlpApplication> _applications = new();

    /// <summary>
    /// 用于保护日志数据访问的读写锁。
    /// </summary>
    private readonly ReaderWriterLockSlim _logsLock = new();
    /// <summary>
    /// 存储日志作用域信息的字典。
    /// </summary>
    private readonly Dictionary<string, OtlpScope> _logScopes = new();
    /// <summary>
    /// 存储日志条目的循环缓冲区。
    /// </summary>
    //private readonly CircularBuffer<OtlpLogEntry> _logs;
    /// <summary>
    /// 存储日志属性键的集合，用于快速查找。
    /// </summary>
    //private readonly HashSet<(OtlpApplication Application, string PropertyKey)> _logPropertyKeys = new();
    /// <summary>
    /// 存储跟踪属性键的集合，用于快速查找。
    /// </summary>
    //private readonly HashSet<(OtlpApplication Application, string PropertyKey)> _tracePropertyKeys = new();
    /// <summary>
    /// 存储每个应用程序未查看的错误日志数量。
    /// </summary>
    private readonly Dictionary<ApplicationKey, int> _applicationUnviewedErrorLogs = new();

    /// <summary>
    /// 用于保护跟踪数据访问的读写锁。
    /// </summary>
    private readonly ReaderWriterLockSlim _tracesLock = new();
    /// <summary>
    /// 存储跟踪作用域信息的字典。
    /// </summary>
    private readonly Dictionary<string, OtlpScope> _traceScopes = new();
    /// <summary>
    /// 存储跟踪条目的循环缓冲区。
    /// </summary>
    private readonly CircularBuffer<OtlpTrace> _traces;
    /// <summary>
    /// 存储跟踪跨度链接的列表。
    /// </summary>
    private readonly List<OtlpSpanLink> _spanLinks = new();
    /// <summary>
    /// Otlp上下文对象，包含日志记录器和配置选项。
    /// </summary>
    internal readonly OtlpContext _otlpContext;

    /// <summary>
    /// 获取或设置是否已经显示过日志数量达到上限的消息。
    /// </summary>
    public bool HasDisplayedMaxLogLimitMessage { get; set; }
    /// <summary>
    /// 获取或设置日志数量达到上限时显示的消息。
    /// </summary>
    public Message? MaxLogLimitMessage { get; set; }

    /// <summary>
    /// 获取或设置是否已经显示过跟踪数量达到上限的消息。
    /// </summary>
    public bool HasDisplayedMaxTraceLimitMessage { get; set; }
    /// <summary>
    /// 获取或设置跟踪数量达到上限时显示的消息。
    /// </summary>
    public Message? MaxTraceLimitMessage { get; set; }

    // For testing.
    /// <summary>
    /// 用于测试的跟踪跨度链接列表。
    /// </summary>
    internal List<OtlpSpanLink> SpanLinks => _spanLinks;
    /// <summary>
    /// 用于测试的跟踪订阅列表。
    /// </summary>
    internal List<Subscription> TracesSubscriptions => _tracesSubscriptions;

    /// <summary>
    /// 构造函数，初始化TelemetryRepository实例。
    /// </summary>
    /// <param name="loggerFactory">日志记录器工厂，用于创建日志记录器。</param>
    /// <param name="dashboardOptions">仪表盘配置选项，包含遥测数据的限制设置。</param>
    /// <param name="pauseManager">暂停管理器，用于控制数据添加操作的暂停状态。</param>
    /// <param name="telemetryDbContext">数据存储的DB</param>
    public TelemetryRepository(ILoggerFactory loggerFactory, IOptions<DashboardOptions> dashboardOptions, PauseManager pauseManager, TelemetryDbContext telemetryDbContext, OtlpConsoleLogService otlpConsoleLogService)
    {
        // 使用日志记录器工厂创建日志记录器
        _logger = loggerFactory.CreateLogger(typeof(TelemetryRepository));
        // 初始化Otlp上下文对象
        _otlpContext = new OtlpContext
        {
            Logger = _logger,
            Options = dashboardOptions.Value.TelemetryLimits
        };
        // 初始化暂停管理器
        _pauseManager = pauseManager;
        this.telemetryDbContext = telemetryDbContext;
        this.otlpConsoleLogService = otlpConsoleLogService;

        // 初始化日志循环缓冲区，设置最大日志数量
        //_logs = new(_otlpContext.Options.MaxLogCount);
        // 初始化跟踪循环缓冲区，设置最大跟踪数量
        _traces = new(_otlpContext.Options.MaxTraceCount);
        // 注册跟踪项移除事件处理程序
        _traces.ItemRemovedForCapacity += TracesItemRemovedForCapacity;
    }

    /// <summary>
    /// 当跟踪项因容量限制被移除时调用的方法，用于清理相关的跨度链接。
    /// </summary>
    /// <param name="trace">被移除的跟踪项。</param>
    private void TracesItemRemovedForCapacity(OtlpTrace trace)
    {
        // 移除中央集合中与被移除跟踪项相关的跨度链接
        foreach (var span in trace.Spans)
        {
            foreach (var link in span.Links)
            {
                _spanLinks.Remove(link);
            }
        }
    }

    /// <summary>
    /// 获取所有应用程序列表。
    /// </summary>
    /// <returns>应用程序列表。</returns>
    public List<OtlpApplication> GetApplications()
    {
        // 调用核心方法获取应用程序列表，不指定名称过滤
        return GetApplicationsCore(name: null);
    }

    /// <summary>
    /// 根据名称获取应用程序列表。
    /// </summary>
    /// <param name="name">应用程序名称。</param>
    /// <returns>匹配名称的应用程序列表。</returns>
    public List<OtlpApplication> GetApplicationsByName(string name)
    {
        // 调用核心方法获取应用程序列表，指定名称过滤
        return GetApplicationsCore(name);
    }

    /// <summary>
    /// 核心方法，根据名称过滤获取应用程序列表。
    /// </summary>
    /// <param name="name">应用程序名称，可为null表示不过滤。</param>
    /// <returns>匹配条件的应用程序列表。</returns>
    private List<OtlpApplication> GetApplicationsCore(string? name)
    {
        // 获取所有应用程序
        IEnumerable<OtlpApplication> results = _applications.Values;
        if (name != null)
        {
            // 根据名称过滤应用程序
            results = results.Where(a => string.Equals(a.ApplicationKey.Name, name, StringComparisons.ResourceName));
        }

        // 对结果按应用程序键排序并转换为列表
        var applications = results.OrderBy(a => a.ApplicationKey).ToList();
        return applications;
    }

    /// <summary>
    /// 根据组合名称获取应用程序。
    /// </summary>
    /// <param name="compositeName">应用程序的组合名称。</param>
    /// <returns>匹配组合名称的应用程序，如果未找到则返回null。</returns>
    public OtlpApplication? GetApplicationByCompositeName(string compositeName)
    {
        // 遍历所有应用程序
        foreach (var kvp in _applications)
        {
            if (kvp.Key.EqualsCompositeName(compositeName))
            {
                // 找到匹配的应用程序
                return kvp.Value;
            }
        }

        // 未找到匹配的应用程序
        return null;
    }

    /// <summary>
    /// 根据应用程序键获取应用程序。
    /// </summary>
    /// <param name="key">应用程序键。</param>
    /// <returns>匹配应用程序键的应用程序，如果未找到则返回null。</returns>
    public OtlpApplication? GetApplication(ApplicationKey key)
    {
        if (key.InstanceId == null)
        {
            // 应用程序键必须包含实例ID
            throw new InvalidOperationException($"{nameof(ApplicationKey)} must have an instance ID.");
        }

        // 尝试从字典中获取应用程序
        _applications.TryGetValue(key, out var application);
        return application;
    }

    /// <summary>
    /// 根据应用程序键获取应用程序列表。
    /// </summary>
    /// <param name="key">应用程序键。</param>
    /// <returns>匹配应用程序键的应用程序列表。</returns>
    public List<OtlpApplication> GetApplications(ApplicationKey key)
    {
        if (key.InstanceId == null)
        {
            // 如果实例ID为空，根据名称获取应用程序列表
            return GetApplicationsByName(key.Name);
        }

        // 根据应用程序键获取单个应用程序并包装成列表
        return [GetApplication(key)];
    }

    /// <summary>
    /// 获取每个应用程序未查看的错误日志数量。
    /// </summary>
    /// <returns>包含应用程序键和未查看错误日志数量的字典。</returns>
    public Dictionary<ApplicationKey, int> GetApplicationUnviewedErrorLogsCount()
    {
        // 进入日志数据的读锁
        _logsLock.EnterReadLock();

        try
        {
            // 返回未查看错误日志数量的副本
            return _applicationUnviewedErrorLogs.ToDictionary();
        }
        finally
        {
            // 退出日志数据的读锁
            _logsLock.ExitReadLock();
        }
    }

    /// <summary>
    /// 标记应用程序的错误日志为已查看。
    /// </summary>
    /// <param name="key">应用程序键，可为null表示标记所有应用程序。</param>
    internal void MarkViewedErrorLogs(ApplicationKey? key)
    {
        // 进入日志数据的写锁
        _logsLock.EnterWriteLock();

        try
        {
            if (key == null)
            {
                // 标记所有日志为已查看
                if (_applicationUnviewedErrorLogs.Count > 0)
                {
                    _applicationUnviewedErrorLogs.Clear();
                    // 触发日志订阅变更事件
                    RaiseSubscriptionChanged(_logSubscriptions);
                }
                return;
            }
            // 获取匹配应用程序键的应用程序列表
            var applications = GetApplications(key.Value);
            foreach (var application in applications)
            {
                // 标记单个应用程序的日志为已查看
                if (_applicationUnviewedErrorLogs.Remove(application.ApplicationKey))
                {
                    // 触发日志订阅变更事件
                    RaiseSubscriptionChanged(_logSubscriptions);
                }
            }
        }
        finally
        {
            // 退出日志数据的写锁
            _logsLock.ExitWriteLock();
        }
    }

    private OtlpApplicationView GetOrAddApplicationView(Resource resource)
    {
        // 检查资源对象是否为空
        ArgumentNullException.ThrowIfNull(resource);
        var key = resource.GetApplicationKey();
        var attributes = resource.Attributes;
        return GetOrAddApplicationView(key, attributes);
    }

    /// <summary>
    /// 获取或添加应用程序视图。
    /// </summary>
    /// <param name="resource">资源对象。</param>
    /// <returns>应用程序视图。</returns>
    private OtlpApplicationView GetOrAddApplicationView(ApplicationKey key, RepeatedField<KeyValue> attributes)
    {
        // 快速路径：尝试从字典中获取应用程序
        if (_applications.TryGetValue(key, out var application))
        {
            // 获取应用程序视图
            return application.GetView(attributes);
        }

        // 较慢的获取或添加路径
        (application, var isNew) = GetOrAddApplication(key);
        if (isNew)
        {
            // 触发应用程序订阅变更事件
            RaiseSubscriptionChanged(_applicationSubscriptions);
        }

        // 获取应用程序视图
        return application.GetView(attributes);

        /// <summary>
        /// 获取或添加应用程序的内部方法。
        /// </summary>
        /// <param name="key">应用程序键。</param>
        /// <returns>应用程序和是否为新添加的标志。</returns>
        (OtlpApplication, bool) GetOrAddApplication(ApplicationKey key)
        {
            // 避免不必要的闭包分配
            var newApplication = false;
            int applicationId = 0;
            applicationId = telemetryDbContext.Db.Queryable<OtlpApplicationEntity>()
                .Where(a => a.Name == key.Name && a.InstanceId == key.InstanceId)
                .Select(_ => _.Id)
                .First();
            // 检查应用程序是否已经存在，如果不存在则添加新的应用程序记录
            if (applicationId == 0)
            {
                // 检查数据数据是否存在application， 如果不存在则添加。 使用telemetryDbContext 进行检查
                if (telemetryDbContext.Db.Queryable<OtlpApplicationEntity>().Any(a => a.Name == key.Name && a.InstanceId == key.InstanceId) == false)
                {
                    // 如果不存在，则添加新的应用程序记录
                    var newApplicationEntity = new OtlpApplicationEntity
                    {
                        Name = key.Name,
                        InstanceId = key.InstanceId
                    };
                    telemetryDbContext.Db.Insertable(newApplicationEntity).ExecuteCommand();
                }
                applicationId = telemetryDbContext.Db.Queryable<OtlpApplicationEntity>()
                        .Where(a => a.Name == key.Name && a.InstanceId == key.InstanceId)
                        .Select(_ => _.Id)
                        .First();
            }

            // 使用GetOrAdd方法获取或添加应用程序
            var application = _applications.GetOrAdd(key, _ =>
            {
                newApplication = true;
                return new OtlpApplication(applicationId, key.Name, key.InstanceId!, _otlpContext);
            });
            return (application, newApplication);
        }
    }

    /// <summary>
    /// 注册新应用程序的订阅回调。
    /// </summary>
    /// <param name="callback">订阅回调函数。</param>
    /// <returns>订阅对象。</returns>
    public Subscription OnNewApplications(Func<Task> callback)
    {
        // 调用添加订阅的核心方法
        return AddSubscription(nameof(OnNewApplications), null, SubscriptionType.Read, callback, _applicationSubscriptions);
    }

    /// <summary>
    /// 注册新日志的订阅回调。
    /// </summary>
    /// <param name="applicationKey">应用程序键，可为null表示所有应用程序。</param>
    /// <param name="subscriptionType">订阅类型。</param>
    /// <param name="callback">订阅回调函数。</param>
    /// <returns>订阅对象。</returns>
    public Subscription OnNewLogs(ApplicationKey? applicationKey, SubscriptionType subscriptionType, Func<Task> callback)
    {
        // 调用添加订阅的核心方法
        return AddSubscription(nameof(OnNewLogs), applicationKey, subscriptionType, callback, _logSubscriptions);
    }

    /// <summary>
    /// 注册新指标的订阅回调。
    /// </summary>
    /// <param name="applicationKey">应用程序键，可为null表示所有应用程序。</param>
    /// <param name="subscriptionType">订阅类型。</param>
    /// <param name="callback">订阅回调函数。</param>
    /// <returns>订阅对象。</returns>
    public Subscription OnNewMetrics(ApplicationKey? applicationKey, SubscriptionType subscriptionType, Func<Task> callback)
    {
        // 调用添加订阅的核心方法
        return AddSubscription(nameof(OnNewMetrics), applicationKey, subscriptionType, callback, _metricsSubscriptions);
    }

    /// <summary>
    /// 注册新跟踪的订阅回调。
    /// </summary>
    /// <param name="applicationKey">应用程序键，可为null表示所有应用程序。</param>
    /// <param name="subscriptionType">订阅类型。</param>
    /// <param name="callback">订阅回调函数。</param>
    /// <returns>订阅对象。</returns>
    public Subscription OnNewTraces(ApplicationKey? applicationKey, SubscriptionType subscriptionType, Func<Task> callback)
    {
        // 调用添加订阅的核心方法
        return AddSubscription(nameof(OnNewTraces), applicationKey, subscriptionType, callback, _tracesSubscriptions);
    }
    public void OnResourceChanges(Action<OtlpResourceView> action, CancellationToken token)
    {
        lock (_resourceSubscriptions)
            _resourceSubscriptions.Add(action);
        token.Register(() =>
        {
            lock (_resourceSubscriptions)
                _resourceSubscriptions.Remove(action);
        });
    }

    /// <summary>
    /// 核心方法，用于添加订阅。
    /// </summary>
    /// <param name="name">订阅名称。</param>
    /// <param name="applicationKey">应用程序键，可为null表示所有应用程序。</param>
    /// <param name="subscriptionType">订阅类型。</param>
    /// <param name="callback">订阅回调函数。</param>
    /// <param name="subscriptions">订阅列表。</param>
    /// <returns>订阅对象。</returns>
    private Subscription AddSubscription(string name, ApplicationKey? applicationKey, SubscriptionType subscriptionType, Func<Task> callback, List<Subscription> subscriptions)
    {
        Subscription? subscription = null;
        // 创建订阅对象
        subscription = new Subscription(name, applicationKey, subscriptionType, callback, () =>
        {
            // 订阅取消时从列表中移除
            lock (_lock)
            {
                subscriptions.Remove(subscription!);
            }
        }, ExecutionContext.Capture(), this);

        // 将订阅对象添加到列表中
        lock (_lock)
        {
            subscriptions.Add(subscription);
        }

        return subscription;
    }

    /// <summary>
    /// 触发订阅变更事件，执行所有订阅的回调函数。
    /// </summary>
    /// <param name="subscriptions">订阅列表。</param>
    private void RaiseSubscriptionChanged(List<Subscription> subscriptions)
    {
        // 加锁确保线程安全
        lock (_lock)
        {
            // 遍历订阅列表并执行回调函数
            foreach (var subscription in subscriptions)
            {
                subscription.Execute();
            }
        }
    }

    /// <summary>
    /// 资源变化
    /// </summary>
    /// <param name="request"></param>
    public void ResourceChanges(ExportRequest request)
    {
        var entity = new OtlpResourceEntity
        {
            NodeId = request.NodeId,
            Ip = request.Ip,
            State = request.State,
            Cpu = request.Cpu,
            UseMem = request.UseMem,
            UseDisk = request.UseDisk,
            UpTcp = request.UpTcp,
            TotalMem = request.TotalMem,
            TotalDisk = request.TotalDisk,
            DownTcp = request.DownTcp,
            ProcessMem = request.ProcessMem,
            ProcessDownTcp = request.ProcessDownTcp,
            ProcessUpTcp = request.ProcessUpTcp,
            AvailableMemory = request.AvailableMemory,
            AvailableDiskSpace = request.AvailableDiskSpace,
            ModifyAt = DateTime.UtcNow
        };
        if (telemetryDbContext.Db.Queryable<OtlpResourceEntity>().Any(_ => _.NodeId == request.NodeId))
        {
            telemetryDbContext.Db.Updateable(entity).ExecuteCommand();
        }
        else
        {
            lock (telemetryDbContext.Db)
            {
                if (telemetryDbContext.Db.Queryable<OtlpResourceEntity>().Any(_ => _.NodeId == request.NodeId))
                {
                    telemetryDbContext.Db.Updateable(entity).ExecuteCommand();
                }
                else
                {
                    telemetryDbContext.Db.Insertable(entity).ExecuteCommand();
                    RaiseSubscriptionChanged(_applicationSubscriptions);
                }
            }
        }
        foreach (var item in _resourceSubscriptions) item.Invoke(new OtlpResourceView(entity));
    }
    public List<OtlpResourceView> GetResources()
    {
        // 删除5分钟不活跃的节点
        lock (telemetryDbContext)
        {
            var compareAt = DateTime.UtcNow.AddMinutes(-5);
            //var oldResourceEntities = telemetryDbContext.Db
            //    .Queryable<OtlpResourceEntity>()
            //    .Where(_ => _.ModifyAt <= compareAt)
            //    .ToList();
            //foreach (var item in oldResourceEntities)
            //{
            //    // 移除不活跃节点的日志
            //    otlpConsoleLogService.RemoveByNode(item.NodeId);
            //}
            telemetryDbContext.Db.Deleteable<OtlpResourceEntity>()
                .Where(_ => _.ModifyAt <= compareAt)
                .ExecuteCommand();

            var list = telemetryDbContext.Db
                .Queryable<OtlpResourceEntity>()
                .OrderByDescending(_ => _.CreateAt)
                .Where(_ => _.CreateAt > compareAt || _.ModifyAt > compareAt)
                .ToList();
            otlpConsoleLogService.RemoveNoExists(list.Select(_ => _.NodeId));
            return list.Select(_ => new OtlpResourceView(_)).ToList();
        }
    }

    /// <summary>
    /// 添加日志数据。
    /// </summary>
    /// <param name="context">添加上下文，包含失败计数等信息。</param>
    /// <param name="resourceLogs">资源日志集合。</param>
    public void AddLogs(AddContext context, RepeatedField<ResourceLogs> resourceLogs)
    {
        if (_pauseManager.AreStructuredLogsPaused(out _))
        {
            // 如果结构化日志添加操作被暂停，记录日志并返回
            _logger.LogTrace("{Count} incoming structured log(s) ignored because of an active pause.", resourceLogs.Count);
            return;
        }

        // 遍历资源日志集合
        foreach (var rl in resourceLogs)
        {
            OtlpApplicationView applicationView;
            try
            {
                // 获取或添加应用程序视图
                applicationView = GetOrAddApplicationView(rl.Resource);
            }
            catch (Exception ex)
            {
                // 记录添加应用程序时的错误
                context.FailureCount += rl.ScopeLogs.Count;
                _otlpContext.Logger.LogInformation(ex, "Error adding application.");
                continue;
            }

            // 调用核心方法添加日志
            AddLogsCore(context, applicationView, rl.ScopeLogs);
        }

        // 触发日志订阅变更事件
        RaiseSubscriptionChanged(_logSubscriptions);
    }

    /// <summary>
    /// 尝试添加作用域信息。
    /// </summary>
    /// <param name="scopes">作用域字典。</param>
    /// <param name="scope">仪器作用域对象。</param>
    /// <param name="s">输出参数，返回添加的作用域对象。</param>
    /// <returns>如果添加成功返回true，否则返回false。</returns>
    private bool TryAddScope(Dictionary<string, OtlpScope> scopes, InstrumentationScope? scope, [NotNullWhen(true)] out OtlpScope? s)
    {
        try
        {
            // 获取作用域名称，如果为空则使用空字符串
            var name = scope?.Name ?? string.Empty;
            // 获取或添加作用域对象
            ref var scopeRef = ref CollectionsMarshal.GetValueRefOrAddDefault(scopes, name, out _);
            // 如果作用域对象不存在则创建
            scopeRef ??= (scope != null) ? new OtlpScope(scope, _otlpContext) : OtlpScope.Empty;
            s = scopeRef;
            return true;
        }
        catch (Exception ex)
        {
            // 记录添加作用域时的错误
            _otlpContext.Logger.LogInformation(ex, "Error adding scope.");
            s = null;
            return false;
        }
    }

    /// <summary>
    /// 核心方法，用于添加日志数据。
    /// </summary>
    /// <param name="context">添加上下文，包含失败计数等信息。</param>
    /// <param name="applicationView">应用程序视图。</param>
    /// <param name="scopeLogs">作用域日志集合。</param>
    public void AddLogsCore(AddContext context, OtlpApplicationView applicationView, RepeatedField<ScopeLogs> scopeLogs)
    {
        // 进入日志数据的写锁
        _logsLock.EnterWriteLock();

        try
        {
            // 遍历作用域日志集合
            foreach (var sl in scopeLogs)
            {
                if (!TryAddScope(_logScopes, sl.Scope, out var scope))
                {
                    // 如果添加作用域失败，增加失败计数并继续
                    context.FailureCount += sl.LogRecords.Count;
                    continue;
                }

                // 遍历日志记录集合
                foreach (var record in sl.LogRecords)
                {
                    try
                    {
                        // 创建日志条目对象
                        var logEntry = new OtlpLogEntry(record, applicationView, scope, _otlpContext);

                        // 插入数据库
                        {
                            var entity = new OtlpLogEntryEntity
                            {
                                Id = logEntry.InternalId,
                                Application = applicationView.ApplicationKey.Name,
                                ApplicationInstanceId = applicationView.ApplicationKey.InstanceId,
                                ApplicationKey = applicationView.ApplicationKey.ToString(),
                                OtlpApplicationId = applicationView.Application.Id,
                                Severity = logEntry.Severity,
                                Message = logEntry.Message,
                                TimeStamp = logEntry.TimeStamp,
                                Attributes = logEntry.Attributes.Select(_ => new AttributeItem { Key = _.Key, Value = _.Value }),
                                Flags = logEntry.Flags,
                                OriginalFormat = logEntry.OriginalFormat ?? "",
                                ParentId = logEntry.ParentId,
                                Category = logEntry.Scope.ScopeName,
                                ScopeVersion = logEntry.Scope.Version,
                                SpanId = logEntry.SpanId,
                                TraceId = logEntry.TraceId,
                            };
                            telemetryDbContext.Db.Insertable(entity).ExecuteCommand();
                        }

                        // 按时间戳插入日志条目
                        //var added = false;
                        //for (var i = _logs.Count - 1; i >= 0; i--)
                        //{
                        //    if (logEntry.TimeStamp > _logs[i].TimeStamp)
                        //    {
                        //        _logs.Insert(i + 1, logEntry);
                        //        added = true;
                        //        break;
                        //    }
                        //}
                        //if (!added)
                        //{
                        //    _logs.Insert(0, logEntry);
                        //}

                        // 对于错误级别及以上的日志，增加未查看计数
                        if (logEntry.Severity >= LogLevel.Error)
                        {
                            // 这里有错误日志了
                            if (!_logSubscriptions.Any(s => s.SubscriptionType == SubscriptionType.Read && (s.ApplicationKey == applicationView.ApplicationKey || s.ApplicationKey == null)))
                            {
                                ref var count = ref CollectionsMarshal.GetValueRefOrAddDefault(_applicationUnviewedErrorLogs, applicationView.ApplicationKey, out _);
                                count++;
                            }
                        }



                        // 记录日志属性键
                        if (logEntry.Attributes.Any())
                        {
                            var list = telemetryDbContext.Db
                                .Queryable<OtlpLogPropertyKeysEntity>()
                                .Where(_ => _.OtlpApplicationId == applicationView.Application.Id)
                                .Select(_ => _.PropertyName)
                                .ToList();

                            var keys = logEntry.Attributes.Select(_ => _.Key);
                            // 查找存在 keys中但是不存在 list中的项
                            var missingKeys = keys.Except(list);
                            if (missingKeys.Any())
                            {
                                var inserts = missingKeys.Select(keyName => new OtlpLogPropertyKeysEntity
                                {
                                    Application = applicationView.ApplicationKey.ToString(),
                                    OtlpApplicationId = applicationView.Application.Id,
                                    PropertyName = keyName,
                                }).ToList();
                                // 记录到DB
                                telemetryDbContext.Db.Insertable(inserts).ExecuteCommand();
                            }

                            //foreach (var kvp in logEntry.Attributes)
                            //{
                            //    _logPropertyKeys.Add((applicationView.Application, kvp.Key));
                            //}
                        }
                    }
                    catch (Exception ex)
                    {
                        // 记录添加日志条目时的错误
                        context.FailureCount++;
                        _otlpContext.Logger.LogInformation(ex, "Error adding log entry.");
                    }
                }
            }
        }
        finally
        {
            // 退出日志数据的写锁
            _logsLock.ExitWriteLock();
        }
    }

    /// <summary>
    /// 根据上下文获取日志数据。
    /// </summary>
    /// <param name="context">获取日志的上下文，包含应用程序键、起始索引、数量和过滤器等信息。</param>
    /// <returns>分页结果，包含日志条目和总数量信息。</returns>
    public PagedResult<OtlpLogEntry> GetLogs(GetLogsContext context)
    {
        // 构建日志查询
        try
        {
            var queryable = telemetryDbContext.Db.Queryable<OtlpLogEntryEntity>();

            if (context.ApplicationKey is not null)
            {
                if (context.ApplicationKey.Value.InstanceId is null)
                    queryable = queryable.Where(_ => _.Application == context.ApplicationKey.Value.Name);
                else
                {
                    var key = context.ApplicationKey.ToString();
                    queryable = queryable.Where(_ => _.ApplicationKey == key);
                }
            }

            // 应用过滤器
            foreach (var filter in context.Filters.GetEnabledFilters())
            {
                var fieldName = TelemetryFilter.ResolveFieldName(filter.Field);
                var val = filter.Value;
                if (fieldName == "Keyword")
                {
                    var searchs = new string[] {
                        nameof(OtlpLogEntryEntity.Message),
                        nameof(OtlpLogEntryEntity.ApplicationKey),
                        nameof(OtlpLogEntryEntity.Attributes),
                    };
                    queryable = queryable.Where(string.Join(
                        " or ",
                        searchs.Select(field => $"{field} LIKE '%{filter.Value}%'")));
                    continue;
                }

                if (fieldName is null)
                {
                    filter.Condition = filter.Condition == FilterCondition.Equals ? FilterCondition.Contains : filter.Condition;
                    filter.Condition = filter.Condition == FilterCondition.NotEqual ? FilterCondition.NotContains : filter.Condition;
                    val = @$"""{filter.Field}"",""Value"":""{filter.Value}""";
                    fieldName = nameof(OtlpLogEntryEntity.Attributes);
                }
                else if (fieldName == nameof(OtlpLogEntryEntity.Severity))
                {
                    val = $"{(int)((LogLevel)Enum.Parse(typeof(LogLevel), filter.Value))}";
                }

                switch (filter.Condition)
                {
                    case FilterCondition.Equals:
                        queryable = queryable.Where($"{fieldName} = '{val}'");
                        break;
                    case FilterCondition.NotEqual:
                        queryable = queryable.Where($"{fieldName} != '{val}'");
                        break;
                    case FilterCondition.NotContains:
                        queryable = queryable.Where($"{fieldName} NOT LIKE '%{val}%'");
                        break;
                    case FilterCondition.Contains:
                        queryable = queryable.Where($"{fieldName} LIKE '%{val}%'");
                        break;
                    case FilterCondition.GreaterThanOrEqual:
                        queryable = queryable.Where($"{fieldName} >= {val}");
                        break;
                    case FilterCondition.GreaterThan:
                        queryable = queryable.Where($"{fieldName} > {val}");
                        break;
                    case FilterCondition.LessThanOrEqual:
                        queryable = queryable.Where($"{fieldName} <= {val}");
                        break;
                    case FilterCondition.LessThan:
                        queryable = queryable.Where($"{fieldName} < {val}");
                        break;
                    default:
                        throw new NotSupportedException($"Filter condition {filter.Condition} is not supported.");
                }
            }

            // 获取总数量
            var totalCount = queryable.Count();

            // 获取分页结果
            var logEntities = queryable
                .OrderByDescending(_ => _.TimeStamp)
               .Skip(context.StartIndex)
               .Take(context.Count)
               .ToList();

            var logs = logEntities.Select(e => new OtlpLogEntry
            {
                TraceId = e.TraceId,
                TimeStamp = e.TimeStamp,
                Attributes = e.Attributes.Select(_ => new KeyValuePair<string, string>(_.Key, _.Value)).ToArray(),
                Flags = (uint)e.Flags,
                InternalId = e.Id,
                Message = e.Message,
                OriginalFormat = e.OriginalFormat,
                ParentId = e.ParentId,
                Severity = e.Severity,
                SpanId = e.SpanId,
                Scope = new OtlpScope(e.Category, e.ScopeVersion),
                ApplicationView = GetOrAddApplicationView(ApplicationKey.Parse(e.ApplicationKey), new RepeatedField<KeyValue>())
            }).ToList();

            return new PagedResult<OtlpLogEntry>
            {
                IsFull = false,
                Items = logs,
                TotalItemCount = totalCount,
            };
        }
        catch (Exception ex)
        {
            Console.WriteLine(" query logs error: {0} ", ex.Message);
            return new PagedResult<OtlpLogEntry>
            {
                IsFull = false,
                Items = new List<OtlpLogEntry>(),
                TotalItemCount = 0,
            };
        }


        //List<OtlpApplication>? applications = null;
        //if (context.ApplicationKey is { } key)
        //{
        //    // 根据应用程序键获取应用程序列表
        //    applications = GetApplications(key);

        //    if (applications.Count == 0)
        //    {
        //        // 如果没有匹配的应用程序，返回空结果
        //        return PagedResult<OtlpLogEntry>.Empty;
        //    }
        //}

        //// 进入日志数据的读锁
        //_logsLock.EnterReadLock();

        //try
        //{
        //    // 获取所有日志条目
        //    var results = _logs.AsEnumerable();
        //    if (applications?.Count > 0)
        //    {
        //        // 根据应用程序过滤日志条目
        //        results = results.Where(l => MatchApplications(l.ApplicationView.ApplicationKey, applications));
        //    }

        //    // 应用过滤器
        //    foreach (var filter in context.Filters.GetEnabledFilters())
        //    {
        //        results = filter.Apply(results);
        //    }

        //    // 获取分页结果
        //    return OtlpHelpers.GetItems(results, context.StartIndex, context.Count, _logs.IsFull);
        //}
        //finally
        //{
        //    // 退出日志数据的读锁
        //    _logsLock.ExitReadLock();
        //}
    }

    /// <summary>
    /// 获取日志属性键列表。
    /// </summary>
    /// <param name="applicationKey">应用程序键，可为null表示所有应用程序。</param>
    /// <returns>日志属性键列表。</returns>
    public List<string> GetLogPropertyKeys(ApplicationKey? applicationKey)
    {
        List<OtlpApplication>? applications = null;
        if (applicationKey != null)
        {
            // 根据应用程序键获取应用程序列表
            applications = GetApplications(applicationKey.Value);
        }

        // 进入日志数据的读锁
        //_logsLock.EnterReadLock();

        try
        {
            return telemetryDbContext.Db
                .Queryable<OtlpLogPropertyKeysEntity>()
                .WhereIF(applications is not null, _ => applications.Select(_ => _.Id).Contains(_.OtlpApplicationId))
                .Select(_ => _.PropertyName)
                .Distinct()
                .ToList();

            //// 获取所有日志属性键
            //var applicationKeys = _logPropertyKeys.AsEnumerable();
            //if (applications?.Count > 0)
            //{
            //    // 根据应用程序过滤日志属性键
            //    applicationKeys = applicationKeys.Where(keys => MatchApplications(keys.Application.ApplicationKey, applications));
            //}

            //// 去重并排序
            //var keys = applicationKeys.Select(keys => keys.PropertyKey).Distinct();
            //return keys.OrderBy(k => k).ToList();
        }
        finally
        {
            // 退出日志数据的读锁
            //_logsLock.ExitReadLock();
        }
    }

    /// <summary>
    /// 获取跟踪属性键列表。
    /// </summary>
    /// <param name="applicationKey">应用程序键，可为null表示所有应用程序。</param>
    /// <returns>跟踪属性键列表。</returns>
    public List<string> GetTracePropertyKeys(ApplicationKey? applicationKey)
    {
        List<OtlpApplication>? applications = null;
        if (applicationKey != null)
        {
            // 根据应用程序键获取应用程序列表
            applications = GetApplications(applicationKey.Value);
        }

        // 进入跟踪数据的读锁
        //_tracesLock.EnterReadLock();

        try
        {
            return telemetryDbContext.Db
                .Queryable<OtlpTracePropertyKeysEntity>()
                .WhereIF(applications is not null, _ => applications.Select(_ => _.Id).Contains(_.OtlpApplicationId))
                .Select(_ => _.PropertyName)
                .Distinct()
                .ToList();

            //// 获取所有跟踪属性键
            //var applicationKeys = _tracePropertyKeys.AsEnumerable();
            //if (applications?.Count > 0)
            //{
            //    // 根据应用程序过滤跟踪属性键
            //    applicationKeys = applicationKeys.Where(keys => MatchApplications(keys.Application.ApplicationKey, applications));
            //}

            //// 去重并排序
            //var keys = applicationKeys.Select(keys => keys.PropertyKey).Distinct();
            //return keys.OrderBy(k => k).ToList();
        }
        finally
        {
            // 退出跟踪数据的读锁
            //_tracesLock.ExitReadLock();
        }
    }

    private List<string> GetTraceIds(GetTracesRequest context, out int total)
    {
        var queryable = telemetryDbContext.Db.Queryable<OtlpTraceEntity>();
        if (context.ApplicationKey is not null)
        {
            if (context.ApplicationKey.Value.InstanceId is null)
                queryable = queryable.Where(_ => _.Application == context.ApplicationKey.Value.Name);
            else
            {
                var key = context.ApplicationKey.ToString();
                queryable = queryable.Where(_ => _.ApplicationKey == key);
            }
        }

        total = queryable.Select(_ => _.TraceId).Distinct().Count();

        var subQuery = queryable.Select(o => new
        {
            o.TraceId,
            o.CreateAt,
        }).OrderByDescending(_ => _.CreateAt);
        var query = telemetryDbContext.Db.Queryable(subQuery);
        return query
               .Select(_ => _.TraceId)
               .Distinct()
               .Skip(context.StartIndex)
               .Take(context.Count)
               .ToList();
    }

    private List<string> GetTraceFilterIds(GetTracesRequest context, out int total)
    {
        var queryable = telemetryDbContext.Db.Queryable<OtlpSpanEntity>();
        if (context.ApplicationKey is not null)
        {
            if (context.ApplicationKey.Value.InstanceId is null)
                queryable = queryable.Where(_ => _.Application == context.ApplicationKey.Value.Name);
            else
            {
                var key = context.ApplicationKey.ToString();
                queryable = queryable.Where(_ => _.ApplicationKey == key);
            }
        }

        if (string.IsNullOrWhiteSpace(context.FilterText) == false)
        {
            context.FilterText = context.FilterText.Replace("'", "''");
            var searchs = new string[] {
                        nameof(OtlpSpanEntity.Name),
                        nameof(OtlpSpanEntity.SpanId),
                        nameof(OtlpSpanEntity.Application),
                        nameof(OtlpSpanEntity.Attributes),
            };


            queryable = queryable.Where(string.Join(
            " or ",
                searchs.Select(field => $@"{field} LIKE '%{context.FilterText}%'")));
        }

        foreach (var filter in context.Filters.GetEnabledFilters())
        {
            var val = filter.Value;
            var fieldName = OtlpSpan.GetFieldName(filter.Field);
            if (fieldName is null)
            {
                filter.Condition = filter.Condition == FilterCondition.Equals ? FilterCondition.Contains : filter.Condition;
                filter.Condition = filter.Condition == FilterCondition.NotEqual ? FilterCondition.NotContains : filter.Condition;
                val = @$"""{filter.Field}"",""Value"":""{filter.Value}""";
                fieldName = nameof(OtlpSpanEntity.Attributes);
            }
            else if (fieldName == nameof(OtlpSpanEntity.Kind))
            {
                val = $"{(int)((OtlpSpanKind)Enum.Parse(typeof(OtlpSpanKind), filter.Value))}";
            }

            switch (filter.Condition)
            {
                case FilterCondition.Equals:
                    queryable = queryable.Where($"{fieldName}] = '{val}'");
                    break;
                case FilterCondition.NotEqual:
                    queryable = queryable.Where($"{fieldName}] != '{val}'");
                    break;
                case FilterCondition.NotContains:
                    queryable = queryable.Where($"{fieldName} NOT LIKE '%{val}%'");
                    break;
                case FilterCondition.Contains:
                    queryable = queryable.Where($"{fieldName} LIKE '%{val}%'");
                    break;
                case FilterCondition.GreaterThanOrEqual:
                    queryable = queryable.Where($"{fieldName} >= {val}");
                    break;
                case FilterCondition.GreaterThan:
                    queryable = queryable.Where($"{fieldName} > {val}");
                    break;
                case FilterCondition.LessThanOrEqual:
                    queryable = queryable.Where($"{fieldName} <= {val}");
                    break;
                case FilterCondition.LessThan:
                    queryable = queryable.Where($"{fieldName} < {val}");
                    break;
                default:
                    throw new NotSupportedException($"Filter condition {filter.Condition} is not supported.");
            }

        }
        total = queryable.Select(_ => _.TraceId).Distinct().Count();

        var subQuery = queryable.Select(o => new
        {
            o.TraceId,
            o.StartTime,
        }).OrderByDescending(_ => _.StartTime);
        var query = telemetryDbContext.Db.Queryable(subQuery);
        return query
               .Select(_ => _.TraceId)
               .Distinct()
               .Skip(context.StartIndex)
               .Take(context.Count)
               .ToList();
        //return queryable
        //       .Select(_ => _.TraceId)
        //       .Distinct()
        //       .Skip(context.StartIndex)
        //       .Take(context.Count)
        //       .ToList();
    }


    /// <summary>
    /// 根据上下文获取跟踪数据。
    /// </summary>
    /// <param name="context">获取跟踪的上下文，包含应用程序键、起始索引、数量、过滤文本和过滤器等信息。</param>
    /// <returns>包含分页结果和最大持续时间的响应对象。</returns>
    public GetTracesResponse GetTraces(GetTracesRequest context)
    {
        List<OtlpTrace> otlpTraces = new List<OtlpTrace>();
        try
        {
            List<string> traces;
            int total = 0;
            var hasFilterText = !string.IsNullOrWhiteSpace(context.FilterText);
            var hasFilter = context.Filters.Any();
            traces = hasFilterText || hasFilter ?
                GetTraceFilterIds(context, out total) : GetTraceIds(context, out total);

            if (traces.Count == 0) return new GetTracesResponse
            {
                PagedResult = new PagedResult<OtlpTrace>
                {
                    IsFull = false,
                    Items = otlpTraces,
                    TotalItemCount = 0
                },
                MaxDuration = TimeSpan.Zero
            };

            foreach (var item in traces)
            {
                var trace = GetTrace(item);
                if (trace is not null)
                    otlpTraces.Add(trace);
                else
                    total--;
            }
            return new GetTracesResponse
            {
                PagedResult = new PagedResult<OtlpTrace>
                {
                    IsFull = false,
                    Items = otlpTraces,
                    TotalItemCount = total
                },
                MaxDuration = otlpTraces.Max(r => r.Duration)
            };
        }
        catch (Exception ex)
        {
            Console.WriteLine(ex.Message);
            return new GetTracesResponse
            {
                PagedResult = new PagedResult<OtlpTrace>
                {
                    IsFull = false,
                    Items = otlpTraces,
                    TotalItemCount = 0
                },
                MaxDuration = TimeSpan.Zero
            };
        }
    }

    /// <summary>
    /// 检查跟踪条目是否匹配应用程序列表中的任何一个。
    /// </summary>
    /// <param name="t">跟踪条目。</param>
    /// <param name="applications">应用程序列表。</param>
    /// <returns>如果匹配返回true，否则返回false。</returns>
    private static bool MatchApplications(OtlpTrace t, List<OtlpApplication> applications)
    {
        // 遍历应用程序列表
        for (var i = 0; i < applications.Count; i++)
        {
            // 遍历跟踪条目的跨度
            foreach (var span in t.Spans)
            {
                if (span.Source.ApplicationKey == applications[i].ApplicationKey)
                {
                    // 找到匹配的跨度
                    return true;
                }
            }
        }

        // 未找到匹配的跨度
        return false;
    }

    /// <summary>
    /// 清除所有信号数据，包括跟踪、结构化日志和指标。
    /// </summary>
    public void ClearAllSignals()
    {
        // 清除跟踪数据
        ClearTraces(null);
        // 清除结构化日志数据
        ClearStructuredLogs(null);
        // 清除指标数据
        ClearMetrics(null);
    }

    /// <summary>
    /// 清除跟踪数据。
    /// </summary>
    /// <param name="applicationKey">应用程序键，可为null表示清除所有应用程序的跟踪数据。</param>
    public void ClearTraces(ApplicationKey? applicationKey = null)
    {
        try
        {
            var deleteable = telemetryDbContext.Db.Deleteable<OtlpTraceEntity>();
            var otlpQueryable = telemetryDbContext.Db.Queryable<OtlpApplicationEntity>();
            // 日志清理
            if (applicationKey is not null)
            {
                if (applicationKey.Value.InstanceId is null)
                {
                    deleteable = deleteable.Where(_ => _.Application == applicationKey.Value.Name);
                    otlpQueryable = otlpQueryable.Where(_ => _.Name == applicationKey.Value.Name);
                }
                else
                {
                    deleteable = deleteable.Where(_ => _.ApplicationKey == applicationKey.Value.ToString());
                    otlpQueryable = otlpQueryable.Where(_ => _.Name == applicationKey.Value.Name && _.InstanceId == applicationKey.Value.InstanceId);
                }
            }
            // 删除子表
            {
                telemetryDbContext.Db.Deleteable<OtlpSpanEntity>()
                 .Where(p => SqlFunc.Subqueryable<OtlpLogEntryEntity>()
                .WhereIF(applicationKey != null && applicationKey.Value.InstanceId == null, _ => _.Application == applicationKey.Value.Name)
                .WhereIF(applicationKey != null && applicationKey.Value.InstanceId == null, _ => _.ApplicationKey == applicationKey.Value.ToString())
                .Where(s => s.TraceId == p.TraceId).Any())
                 .ExecuteCommand();
                telemetryDbContext.Db.Deleteable<OtlpSpanLinkEntity>()
                 .Where(p => SqlFunc.Subqueryable<OtlpLogEntryEntity>()
                .WhereIF(applicationKey != null && applicationKey.Value.InstanceId == null, _ => _.Application == applicationKey.Value.Name)
                .WhereIF(applicationKey != null && applicationKey.Value.InstanceId == null, _ => _.ApplicationKey == applicationKey.Value.ToString()).Where(s => s.TraceId == p.TraceId).Any())
                 .ExecuteCommand();
                telemetryDbContext.Db.Deleteable<OtlpSpanEventEntity>()
                 .Where(p => SqlFunc.Subqueryable<OtlpLogEntryEntity>()
                .WhereIF(applicationKey != null && applicationKey.Value.InstanceId == null, _ => _.Application == applicationKey.Value.Name)
                .WhereIF(applicationKey != null && applicationKey.Value.InstanceId == null, _ => _.ApplicationKey == applicationKey.Value.ToString()).Where(s => s.TraceId == p.TraceId).Any())
                 .ExecuteCommand();
                var applicationIds = otlpQueryable.Select(_ => _.Id).ToList();
                telemetryDbContext.Db.Deleteable<OtlpTracePropertyKeysEntity>()
                 .Where(p => applicationIds.Contains(p.OtlpApplicationId))
                 .ExecuteCommand();
            }

            deleteable.ExecuteCommand();
        }
        catch (Exception ex)
        {
            Console.WriteLine("ClearTraces error: {0}", ex.Message);
        }

        // 触发跟踪订阅变更事件
        RaiseSubscriptionChanged(_tracesSubscriptions);
    }

    /// <summary>
    /// 清除结构化日志数据。
    /// </summary>
    /// <param name="applicationKey">应用程序键，可为null表示清除所有应用程序的结构化日志数据。</param>
    public void ClearStructuredLogs(ApplicationKey? applicationKey = null)
    {
        var deleteable = telemetryDbContext.Db.Deleteable<OtlpLogEntryEntity>();
        // 日志清理
        if (applicationKey is not null)
        {
            if (applicationKey.Value.InstanceId is null)
                deleteable = deleteable.Where(_ => _.Application == applicationKey.Value.Name);
            else
                deleteable = deleteable.Where(_ => _.ApplicationKey == applicationKey.Value.ToString());
        }
        deleteable.ExecuteCommand();
        RaiseSubscriptionChanged(_logSubscriptions);
    }

    /// <summary>
    /// 清除指标数据。
    /// </summary>
    /// <param name="applicationKey">应用程序键，可为null表示清除所有应用程序的指标数据。</param>
    public void ClearMetrics(ApplicationKey? applicationKey = null)
    {
        List<OtlpApplication> applications;
        if (applicationKey.HasValue)
        {
            // 根据应用程序键获取应用程序列表
            applications = GetApplications(applicationKey.Value);
        }
        else
        {
            // 获取所有应用程序列表
            applications = _applications.Values.ToList();
        }

        // 遍历应用程序列表并清除指标数据
        foreach (var app in applications)
        {
            app.ClearMetrics();
        }

        // 触发指标订阅变更事件
        RaiseSubscriptionChanged(_metricsSubscriptions);
    }

    /// <summary>
    /// 获取跟踪字段值的统计信息。
    /// </summary>
    /// <param name="attributeName">属性名称。</param>
    /// <returns>包含属性值和出现次数的字典。</returns>
    public Dictionary<string, int> GetTraceFieldValues(string attributeName)
    {
        // 进入跟踪数据的读锁
        _tracesLock.EnterReadLock();

        var attributesValues = new Dictionary<string, int>(StringComparers.OtlpAttribute);

        try
        {
            // 遍历所有跟踪条目
            foreach (var trace in _traces)
            {
                // 遍历跟踪条目的跨度
                foreach (var span in trace.Spans)
                {
                    // 获取属性值
                    var value = OtlpSpan.GetFieldValue(span, attributeName);
                    if (value != null)
                    {
                        // 统计属性值的出现次数
                        ref var count = ref CollectionsMarshal.GetValueRefOrAddDefault(attributesValues, value, out _);
                        count++;
                    }
                }
            }
        }
        finally
        {
            // 退出跟踪数据的读锁
            _tracesLock.ExitReadLock();
        }

        return attributesValues;
    }

    /// <summary>
    /// 获取日志字段值的统计信息。
    /// </summary>
    /// <param name="attributeName">属性名称。</param>
    /// <returns>包含属性值和出现次数的字典。</returns>
    public Dictionary<string, int> GetLogsFieldValues(string attributeName)
    {
        // 这里是筛选的时候，做提示用的 这里直接返回空。 让用户去查询
        return new Dictionary<string, int>(StringComparers.OtlpAttribute);

        //// 使用 telemetryDbContext.Db 进行数据库查询
        //var fieldName = OtlpLogEntry.GetFieldName(attributeName);
        //var query = telemetryDbContext.Db
        //    .Queryable<OtlpLogEntryEntity>()
        //   .Select($"[{fieldName}]")
        //   .GroupBy($"[{fieldName}]")
        //   .Select($"[{attributeName}], COUNT(*) as Count");

        //var results = query.ToList<dynamic>();

        //var attributesValues = new Dictionary<string, int>(StringComparers.OtlpAttribute);

        //foreach (var result in results)
        //{
        //    var value = result[attributeName]?.ToString();
        //    var count = Convert.ToInt32(result["Count"]);

        //    if (value != null)
        //    {
        //        attributesValues[value] = count;
        //    }
        //}

        //return attributesValues;

        //// 进入日志数据的读锁
        //_logsLock.EnterReadLock();

        //var attributesValues = new Dictionary<string, int>(StringComparers.OtlpAttribute);

        //try
        //{


        //    // 遍历所有日志条目
        //    foreach (var log in _logs)
        //    {
        //        // 获取属性值
        //        var value = OtlpLogEntry.GetFieldValue(log, attributeName);
        //        if (value != null)
        //        {
        //            // 统计属性值的出现次数
        //            ref var count = ref CollectionsMarshal.GetValueRefOrAddDefault(attributesValues, value, out _);
        //            count++;
        //        }
        //    }
        //}
        //finally
        //{
        //    // 退出日志数据的读锁
        //    _logsLock.ExitReadLock();
        //}

        //return attributesValues;
    }

    /// <summary>
    /// 从数据库中根据跟踪ID获取跟踪条目。
    /// </summary>
    /// <param name="traceId">跟踪ID。</param>
    /// <returns>匹配跟踪ID的跟踪条目，如果未找到则返回null。</returns>
    public OtlpTrace? GetTraceFromDb(string traceId)
    {
        try
        {
            // 从数据库中查询跟踪记录
            var traceEntity = telemetryDbContext.Db
               .Queryable<OtlpTraceEntity>()
               .Where(_ => _.TraceId == traceId)
               .First();

            if (traceEntity == null)
            {
                return null;
            }

            // 从数据库中查询该跟踪下的所有跨度记录
            var spanEntities = telemetryDbContext.Db
               .Queryable<OtlpSpanEntity>()
               .OrderBy(_ => _.StartTime)
               .Where(_ => _.TraceId == traceEntity.TraceId)
               .ToList();

            if (spanEntities.Any() == false) return null;

            // 创建OtlpTrace对象
            var trace = new OtlpTrace(traceEntity.TraceId);

            // 创建并添加OtlpSpan对象到OtlpTrace
            foreach (var spanEntity in spanEntities)
            {
                var applicationView = GetOrAddApplicationView(ApplicationKey.Parse(spanEntity.ApplicationKey), new RepeatedField<KeyValue>());
                var scope = new OtlpScope(spanEntity.Category, spanEntity.ScopeVersion);

                var span = new OtlpSpan(applicationView, trace, scope)
                {
                    SpanId = spanEntity.SpanId,
                    ParentSpanId = spanEntity.ParentSpanId,
                    Name = spanEntity.Name,
                    Kind = (OtlpSpanKind)spanEntity.Kind,
                    StartTime = spanEntity.StartTime,
                    EndTime = spanEntity.EndTime,
                    Status = (OtlpSpanStatusCode)spanEntity.Status,
                    StatusMessage = spanEntity.StatusMessage,
                    State = spanEntity.State,
                    Attributes = spanEntity.Attributes.Select(_ => new KeyValuePair<string, string>(_.Key, _.Value)).ToArray(),
                    Links = new List<OtlpSpanLink>(),
                    BackLinks = new List<OtlpSpanLink>(),
                    Events = new List<OtlpSpanEvent>()
                };

                // 从数据库中查询该跨度的所有链接记录
                var linkEntities = telemetryDbContext.Db
                   .Queryable<OtlpSpanLinkEntity>()
                   .Where(_ => _.OtlSpanId == spanEntity.Id)
                   .ToList();

                // 创建并添加OtlpSpanLink对象到OtlpSpan
                foreach (var linkEntity in linkEntities)
                {
                    var link = new OtlpSpanLink
                    {
                        SourceSpanId = linkEntity.SourceSpanId,
                        SourceTraceId = linkEntity.SourceTraceId,
                        TraceState = linkEntity.TraceState,
                        SpanId = linkEntity.SpanId,
                        TraceId = linkEntity.TraceId,
                        Attributes = linkEntity.Attributes.Select(_ => new KeyValuePair<string, string>(_.Key, _.Value)).ToArray()
                    };

                    span.Links.Add(link);
                }

                // 从数据库中查询该跨度的所有事件记录
                var eventEntities = telemetryDbContext.Db
                   .Queryable<OtlpSpanEventEntity>()
                   .OrderBy(_ => _.Time)
                   .Where(_ => _.OtlpSpanId == spanEntity.Id)
                   .ToList();

                // 创建并添加 OtlpSpanEvent 对象到 OtlpSpan
                foreach (var eventEntity in eventEntities)
                {
                    var spanEvent = new OtlpSpanEvent(span)
                    {
                        InternalId = eventEntity.Id,
                        Time = eventEntity.Time,
                        Name = eventEntity.Name,
                        Attributes = eventEntity.Attributes.Select(_ => new KeyValuePair<string, string>(_.Key, _.Value)).ToArray()
                    };
                    span.Events.Add(spanEvent);
                }
                trace.AddSpan(span);
            }

            return trace;
        }
        catch (Exception ex)
        {
            _otlpContext.Logger.LogError(ex, $"Error getting trace from database with ID: {traceId}");
            return null;
        }
    }

    /// <summary>
    /// 根据跟踪ID获取跟踪条目。
    /// </summary>
    /// <param name="traceId">跟踪ID。</param>
    /// <returns>匹配跟踪ID的跟踪条目，如果未找到则返回null。</returns>
    public OtlpTrace? GetTrace(string traceId)
    {
        return GetTraceFromDb(traceId);
    }

    /// <summary>
    /// 内部方法，在持有锁的情况下根据跟踪ID获取跟踪条目。
    /// </summary>
    /// <param name="traceId">跟踪ID。</param>
    /// <returns>匹配跟踪ID的跟踪条目，如果未找到则返回null。</returns>
    private OtlpTrace? GetTraceUnsynchronized(string traceId)
    {
        // 确保已经持有锁
        Debug.Assert(_tracesLock.IsReadLockHeld || _tracesLock.IsWriteLockHeld, $"Must get lock before calling {nameof(GetTraceUnsynchronized)}.");

        try
        {
            // 过滤跟踪条目
            var results = _traces.Where(t => t.TraceId.StartsWith(traceId, StringComparison.Ordinal));
            // 获取单个匹配的跟踪条目
            var trace = results.SingleOrDefault();
            return trace is not null ? OtlpTrace.Clone(trace) : null;
        }
        catch (Exception ex)
        {
            // 处理多个跟踪条目匹配的异常
            throw new InvalidOperationException($"Multiple traces found with trace id '{traceId}'.", ex);
        }
    }

    /// <summary>
    /// 内部方法，在持有锁的情况下根据跟踪ID和跨度ID获取跨度条目。
    /// </summary>
    /// <param name="traceId">跟踪ID。</param>
    /// <param name="spanId">跨度ID。</param>
    /// <returns>匹配跟踪ID和跨度ID的跨度条目，如果未找到则返回null。</returns>
    private OtlpSpan? GetSpanUnsynchronized(string traceId, string spanId)
    {
        // 确保已经持有锁
        Debug.Assert(_tracesLock.IsReadLockHeld || _tracesLock.IsWriteLockHeld, $"Must get lock before calling {nameof(GetSpanUnsynchronized)}.");

        // 获取跟踪条目
        var trace = GetTraceUnsynchronized(traceId);
        if (trace != null)
        {
            // 遍历跟踪条目的跨度
            foreach (var span in trace.Spans)
            {
                if (span.SpanId == spanId)
                {
                    // 找到匹配的跨度条目
                    return span;
                }
            }
        }

        // 未找到匹配的跨度条目
        return null;
    }

    /// <summary>
    /// 根据跟踪ID和跨度ID获取跨度条目。
    /// </summary>
    /// <param name="traceId">跟踪ID。</param>
    /// <param name="spanId">跨度ID。</param>
    /// <returns>匹配跟踪ID和跨度ID的跨度条目，如果未找到则返回null。</returns>
    public OtlpSpan? GetSpan(string traceId, string spanId)
    {
        // 进入跟踪数据的读锁
        _tracesLock.EnterReadLock();

        try
        {
            // 调用内部方法获取跨度条目
            return GetSpanUnsynchronized(traceId, spanId);
        }
        finally
        {
            // 退出跟踪数据的读锁
            _tracesLock.ExitReadLock();
        }
    }

    /// <summary>
    /// 添加指标数据。
    /// </summary>
    /// <param name="context">添加上下文，包含失败计数等信息。</param>
    /// <param name="resourceMetrics">资源指标集合。</param>
    public void AddMetrics(AddContext context, RepeatedField<ResourceMetrics> resourceMetrics)
    {
        if (_pauseManager.AreMetricsPaused(out _))
        {
            // 如果指标添加操作被暂停，记录日志并返回
            _logger.LogTrace("{Count} incoming metric(s) ignored because of an active pause.", resourceMetrics.Count);
            return;
        }

        // 遍历资源指标集合
        foreach (var rm in resourceMetrics)
        {
            OtlpApplicationView applicationView;
            try
            {
                // 获取或添加应用程序视图
                applicationView = GetOrAddApplicationView(rm.Resource);
            }
            catch (Exception ex)
            {
                // 记录添加应用程序时的错误
                context.FailureCount += rm.ScopeMetrics.Sum(s => s.Metrics.Count);
                _otlpContext.Logger.LogInformation(ex, "Error adding application.");
                continue;
            }

            // 调用应用程序的添加指标方法
            applicationView.Application.AddMetrics(context, rm.ScopeMetrics);
        }

        // 触发指标订阅变更事件
        RaiseSubscriptionChanged(_metricsSubscriptions);
    }

    /// <summary>
    /// 添加跟踪数据。
    /// </summary>
    /// <param name="context">添加上下文，包含失败计数等信息。</param>
    /// <param name="resourceSpans">资源跨度集合。</param>
    public void AddTraces(AddContext context, RepeatedField<ResourceSpans> resourceSpans)
    {
        if (_pauseManager.AreTracesPaused(out _))
        {
            // 如果跟踪添加操作被暂停，记录日志并返回
            _logger.LogTrace("{Count} incoming trace(s) ignored because of an active pause.", resourceSpans.Count);
            return;
        }

        // 遍历资源跨度集合
        foreach (var rs in resourceSpans)
        {
            OtlpApplicationView applicationView;
            try
            {
                // 获取或添加应用程序视图
                applicationView = GetOrAddApplicationView(rs.Resource);
            }
            catch (Exception ex)
            {
                // 记录添加应用程序时的错误
                context.FailureCount += rs.ScopeSpans.Sum(s => s.Spans.Count);
                _otlpContext.Logger.LogInformation(ex, "Error adding application.");
                continue;
            }

            // 调用核心方法添加跟踪数据
            //AddTracesCore(context, applicationView, rs.ScopeSpans);
            AddTracesCoreToDb(context, applicationView, rs.ScopeSpans);
        }

        // 触发跟踪订阅变更事件
        RaiseSubscriptionChanged(_tracesSubscriptions);
    }

    /// <summary>
    /// 将状态码转换为OtlpSpanStatusCode枚举值。
    /// </summary>
    /// <param name="status">状态对象。</param>
    /// <returns>转换后的OtlpSpanStatusCode枚举值。</returns>
    private static OtlpSpanStatusCode ConvertStatus(Status? status)
    {
        return status?.Code switch
        {
            Status.Types.StatusCode.Ok => OtlpSpanStatusCode.Ok,
            Status.Types.StatusCode.Error => OtlpSpanStatusCode.Error,
            Status.Types.StatusCode.Unset => OtlpSpanStatusCode.Unset,
            _ => OtlpSpanStatusCode.Unset
        };
    }

    /// <summary>
    /// 将跨度类型转换为OtlpSpanKind枚举值。
    /// </summary>
    /// <param name="kind">跨度类型对象。</param>
    /// <returns>转换后的OtlpSpanKind枚举值。</returns>
    internal static OtlpSpanKind ConvertSpanKind(SpanKind? kind)
    {
        return kind switch
        {
            // Unspecified to Internal is intentional.
            // "Implementations MAY assume SpanKind to be INTERNAL when receiving UNSPECIFIED."
            SpanKind.Unspecified => OtlpSpanKind.Internal,
            SpanKind.Internal => OtlpSpanKind.Internal,
            SpanKind.Client => OtlpSpanKind.Client,
            SpanKind.Server => OtlpSpanKind.Server,
            SpanKind.Producer => OtlpSpanKind.Producer,
            SpanKind.Consumer => OtlpSpanKind.Consumer,
            _ => OtlpSpanKind.Unspecified
        };
    }

    /// <summary>
    /// 核心方法，用于添加跟踪数据。
    /// </summary>
    /// <param name="context">添加上下文，包含失败计数等信息。</param>
    /// <param name="applicationView">应用程序视图。</param>
    /// <param name="scopeSpans">作用域跨度集合。</param>
    internal void AddTracesCore(AddContext context, OtlpApplicationView applicationView, RepeatedField<ScopeSpans> scopeSpans)
    {
        // 进入跟踪数据的写锁
        _tracesLock.EnterWriteLock();

        try
        {
            // 遍历作用域跨度集合
            foreach (var scopeSpan in scopeSpans)
            {
                if (!TryAddScope(_traceScopes, scopeSpan.Scope, out var scope))
                {
                    // 如果添加作用域失败，增加失败计数并继续
                    context.FailureCount += scopeSpan.Spans.Count;
                    continue;
                }

                OtlpTrace? lastTrace = null;

                // 遍历跨度集合
                foreach (var span in scopeSpan.Spans)
                {
                    try
                    {
                        OtlpTrace? trace;
                        bool newTrace = false;

                        // 快速路径：检查跨度是否与上一个跨度在同一跟踪中
                        if (lastTrace != null && span.TraceId.Span.SequenceEqual(lastTrace.Key.Span))
                        {
                            trace = lastTrace;
                        }
                        else if (!TryGetTraceById(_traces, span.TraceId.Memory, out trace))
                        {
                            // 创建新的跟踪条目
                            trace = new OtlpTrace(span.TraceId.Memory);
                            newTrace = true;
                        }

                        // 创建新的跨度条目
                        var newSpan = CreateSpan(applicationView, span, trace, scope, _otlpContext);
                        // 将新跨度添加到跟踪中
                        trace.AddSpan(newSpan);

                        // 处理跨度链接
                        foreach (var existingLink in _spanLinks)
                        {
                            if (existingLink.SpanId == newSpan.SpanId && existingLink.TraceId == newSpan.TraceId)
                            {
                                newSpan.BackLinks.Add(existingLink);
                            }
                        }

                        // 添加跨度链接到中央集合
                        foreach (var link in newSpan.Links)
                        {
                            _spanLinks.Add(link);

                            var linkedSpan = GetSpanUnsynchronized(link.TraceId, link.SpanId);
                            linkedSpan?.BackLinks.Add(link);
                        }

                        // 确保跟踪按时间顺序排列
                        if (newTrace)
                        {
                            var added = false;
                            for (var i = _traces.Count - 1; i >= 0; i--)
                            {
                                var currentTrace = _traces[i];
                                if (trace.FirstSpan.StartTime > currentTrace.FirstSpan.StartTime)
                                {
                                    _traces.Insert(i + 1, trace);
                                    added = true;
                                    break;
                                }
                            }
                            if (!added)
                            {
                                _traces.Insert(0, trace);
                            }
                        }
                        else
                        {
                            if (trace.FirstSpan == newSpan)
                            {
                                var moved = false;
                                var index = _traces.IndexOf(trace);

                                for (var i = index - 1; i >= 0; i--)
                                {
                                    var currentTrace = _traces[i];
                                    if (trace.FirstSpan.StartTime > currentTrace.FirstSpan.StartTime)
                                    {
                                        var insertPosition = i + 1;
                                        if (index != insertPosition)
                                        {
                                            _traces.RemoveAt(index);
                                            _traces.Insert(insertPosition, trace);
                                        }
                                        moved = true;
                                        break;
                                    }
                                }
                                if (!moved)
                                {
                                    if (index != 0)
                                    {
                                        _traces.RemoveAt(index);
                                        _traces.Insert(0, trace);
                                    }
                                }
                            }
                        }


                        // 记录跟踪属性键
                        if (newSpan.Attributes.Any())
                        {
                            var list = telemetryDbContext.Db
                                .Queryable<OtlpTracePropertyKeysEntity>()
                                .Where(_ => _.OtlpApplicationId == applicationView.Application.Id)
                                .Select(_ => _.PropertyName)
                                .ToList();

                            var keys = newSpan.Attributes.Select(_ => _.Key);
                            // 查找存在 keys中但是不存在 list中的项
                            var missingKeys = keys.Except(list);
                            if (missingKeys.Any())
                            {
                                var inserts = missingKeys.Select(keyName => new OtlpTracePropertyKeysEntity
                                {
                                    Application = applicationView.ApplicationKey.ToString(),
                                    OtlpApplicationId = applicationView.Application.Id,
                                    PropertyName = keyName,
                                }).ToList();
                                // 记录到DB
                                telemetryDbContext.Db.Insertable(inserts).ExecuteCommand();
                            }
                        }


                        // 记录跟踪属性键
                        // foreach (var kvp in newSpan.Attributes)
                        // {
                        //     _tracePropertyKeys.Add((applicationView.Application, kvp.Key));
                        // }

                        // 确保新添加或更新的跟踪在集合中
                        Debug.Assert(_traces.Contains(trace), "Trace not found in traces collection.");

                        lastTrace = trace;
                    }
                    catch (Exception ex)
                    {
                        // 记录添加跨度时的错误
                        context.FailureCount++;
                        _otlpContext.Logger.LogInformation(ex, "Error adding span.");
                    }

                    // 调试时检查跟踪顺序和跨度链接
                    AssertTraceOrder();
                    AssertSpanLinks();
                }

            }
        }
        finally
        {
            // 退出跟踪数据的写锁
            _tracesLock.ExitWriteLock();
        }


    }

    /// <summary>
    /// 核心方法，用于将跟踪数据添加到数据库。
    /// </summary>
    /// <param name="context">添加上下文，包含失败计数等信息。</param>
    /// <param name="applicationView">应用程序视图。</param>
    /// <param name="scopeSpans">作用域跨度集合。</param>
    internal void AddTracesCoreToDb(AddContext context, OtlpApplicationView applicationView, RepeatedField<ScopeSpans> scopeSpans)
    {
        // 进入跟踪数据的写锁
        _tracesLock.EnterWriteLock();

        try
        {
            // 遍历作用域跨度集合
            foreach (var scopeSpan in scopeSpans)
            {
                if (!TryAddScope(_traceScopes, scopeSpan.Scope, out var scope))
                {
                    // 如果添加作用域失败，增加失败计数并继续
                    context.FailureCount += scopeSpan.Spans.Count;
                    continue;
                }
                OtlpTrace? lastTrace = null;
                OtlpTraceEntity? lastTraceEntity = null;
                // 遍历跨度集合
                foreach (var span in scopeSpan.Spans)
                {
                    try
                    {
                        OtlpTrace? trace;
                        OtlpTraceEntity? traceEntity;

                        // 快速路径：检查跨度是否与上一个跨度在同一跟踪中
                        if (lastTrace != null && span.TraceId.Span.SequenceEqual(lastTrace.Key.Span))
                        {
                            trace = lastTrace;
                            traceEntity = lastTraceEntity;
                        }
                        // 先尝试从现有数据中获取跟踪记录
                        else if (!TryGetTraceById(_traces, span.TraceId.Memory, out trace))
                        {
                            // 创建新的跟踪条目
                            lastTrace = trace = new OtlpTrace(span.TraceId.Memory);
                            // 存储新的跟踪记录到数据库
                            lastTraceEntity = traceEntity = new OtlpTraceEntity
                            {
                                TraceId = trace.TraceId,
                                OtlpApplicationId = applicationView.Application.Id,
                                Application = applicationView.ApplicationKey.Name,
                                ApplicationInstanceId = applicationView.ApplicationKey.InstanceId,
                                ApplicationKey = applicationView.ApplicationKey.ToString(),
                                //FullName = trace.FullName,
                            };

                            var queryable = telemetryDbContext.Db.Queryable<OtlpTraceEntity>();
                            queryable = queryable.Where(_ => _.TraceId == trace.TraceId && _.OtlpApplicationId == applicationView.Application.Id);
                            lastTraceEntity = queryable.First();
                            if (lastTraceEntity is null)
                                lastTraceEntity = traceEntity = telemetryDbContext.Db.Insertable(traceEntity).ExecuteReturnEntity();
                        }
                        else if (lastTraceEntity is null)
                        {
                            // 存储新的跟踪记录到数据库
                            lastTraceEntity = traceEntity = new OtlpTraceEntity
                            {
                                TraceId = trace.TraceId,
                                OtlpApplicationId = applicationView.Application.Id,
                                Application = applicationView.ApplicationKey.ToString(),
                                //FullName = trace.FullName,
                            };
                            var queryable = telemetryDbContext.Db.Queryable<OtlpTraceEntity>();
                            queryable = queryable.Where(_ => _.TraceId == trace.TraceId && _.OtlpApplicationId == applicationView.Application.Id);
                            lastTraceEntity = queryable.First();
                            if (lastTraceEntity is null)
                                lastTraceEntity = traceEntity = telemetryDbContext.Db.Insertable(traceEntity).ExecuteReturnEntity();
                        }

                        // 创建新的跨度条目
                        var newSpan = CreateSpan(applicationView, span, trace, scope, _otlpContext);
                        // 存储跨度数据到数据库
                        var spanEntity = new OtlpSpanEntity
                        {
                            TraceId = newSpan.TraceId,
                            SpanId = newSpan.SpanId,
                            ParentSpanId = newSpan.ParentSpanId,
                            Name = newSpan.Name,
                            Kind = newSpan.Kind,
                            StartTime = newSpan.StartTime,
                            EndTime = newSpan.EndTime,
                            Status = newSpan.Status,
                            StatusMessage = newSpan.StatusMessage ?? string.Empty,
                            State = newSpan.State ?? string.Empty,
                            OtlpApplicationId = applicationView.Application.Id,
                            Application = applicationView.ApplicationKey.Name,
                            ApplicationInstanceId = applicationView.ApplicationKey.InstanceId,
                            ApplicationKey = applicationView.ApplicationKey.ToString(),
                            Attributes = newSpan.Attributes.Select(_ => new AttributeItem { Key = _.Key, Value = _.Value }),
                            OtlpTraceId = lastTraceEntity.Id, // 关联到对应的跟踪记录
                            Category = scope.ScopeName,
                            ScopeVersion = scope.Version
                        };

                        spanEntity = telemetryDbContext.Db.Insertable(spanEntity).ExecuteReturnEntity();

                        // 存储跨度链接数据到数据库
                        var links = newSpan.Links.Select(link => new OtlpSpanLinkEntity
                        {
                            OtlSpanId = spanEntity.Id,
                            SourceSpanId = link.SourceSpanId,
                            SourceTraceId = link.SourceTraceId,
                            TraceState = link.TraceState,
                            SpanId = link.SpanId,
                            TraceId = link.TraceId,
                            OtlpApplicationId = applicationView.Application.Id,
                            Attributes = newSpan.Attributes.Select(_ => new AttributeItem { Key = _.Key, Value = _.Value }),
                        }).ToList();
                        telemetryDbContext.Db.Insertable(links).ExecuteCommand();

                        // 存储跨度事件数据到数据库
                        if (newSpan.Events.Any())
                        {
                            var events = newSpan.Events.Select(spanEvent => new OtlpSpanEventEntity
                            {
                                Id = spanEvent.InternalId,
                                TraceId = spanEntity.TraceId,
                                OtlpSpanId = spanEntity.Id,
                                Name = spanEvent.Name,
                                Time = spanEvent.Time,
                                Attributes = spanEvent.Attributes.Select(_ => new AttributeItem { Key = _.Key, Value = _.Value })
                            }).ToList();
                            telemetryDbContext.Db.Insertable(events).ExecuteCommand();
                        }

                        // 记录跟踪属性键
                        if (newSpan.Attributes.Any())
                        {
                            var list = telemetryDbContext.Db
                                .Queryable<OtlpTracePropertyKeysEntity>()
                                .Where(_ => _.OtlpApplicationId == applicationView.Application.Id)
                                .Select(_ => _.PropertyName)
                                .ToList();

                            var keys = newSpan.Attributes.Select(_ => _.Key);
                            // 查找存在 keys中但是不存在 list中的项
                            var missingKeys = keys.Except(list);
                            if (missingKeys.Any())
                            {
                                var inserts = missingKeys.Select(keyName => new OtlpTracePropertyKeysEntity
                                {
                                    Application = applicationView.ApplicationKey.ToString(),
                                    OtlpApplicationId = applicationView.Application.Id,
                                    PropertyName = keyName,
                                }).ToList();
                                // 记录到DB
                                telemetryDbContext.Db.Insertable(inserts).ExecuteCommand();
                            }
                        }
                    }
                    catch (Exception ex)
                    {
                        // 记录添加跨度时的错误
                        context.FailureCount++;
                        _otlpContext.Logger.LogInformation(ex, "Error adding span to database.");
                    }
                }
            }
        }
        finally
        {
            // 退出跟踪数据的写锁
            _tracesLock.ExitWriteLock();
        }
    }

    /// <summary>
    /// 尝试根据跟踪ID从循环缓冲区中获取跟踪条目。
    /// </summary>
    /// <param name="traces">跟踪条目循环缓冲区。</param>
    /// <param name="traceId">跟踪ID。</param>
    /// <param name="trace">输出参数，返回匹配的跟踪条目。</param>
    /// <returns>如果找到匹配的跟踪条目返回true，否则返回false。</returns>
    static bool TryGetTraceById(CircularBuffer<OtlpTrace> traces, ReadOnlyMemory<byte> traceId, [NotNullWhen(true)] out OtlpTrace? trace)
    {
        var s = traceId.Span;
        for (var i = traces.Count - 1; i >= 0; i--)
        {
            if (traces[i].Key.Span.SequenceEqual(s))
            {
                // 找到匹配的跟踪条目
                trace = traces[i];
                return true;
            }
        }

        // 未找到匹配的跟踪条目
        trace = null;
        return false;
    }

    /// <summary>
    /// 调试时检查跟踪条目的顺序是否正确。
    /// </summary>
    [Conditional("DEBUG")]
    private void AssertTraceOrder()
    {
        DateTime current = default;
        for (var i = 0; i < _traces.Count; i++)
        {
            var trace = _traces[i];
            if (trace.FirstSpan.StartTime < current)
            {
                // 跟踪条目顺序错误，抛出异常
                throw new InvalidOperationException($"Traces not in order at index {i}.");
            }

            current = trace.FirstSpan.StartTime;
        }
    }

    /// <summary>
    /// 调试时检查跨度链接是否正确。
    /// </summary>
    [Conditional("DEBUG")]
    private void AssertSpanLinks()
    {
        // 创建跨度链接的本地副本
        var currentSpanLinks = _spanLinks.ToList();

        // 移除与跨度匹配的跨度链接
        foreach (var trace in _traces)
        {
            foreach (var span in trace.Spans)
            {
                foreach (var link in span.Links)
                {
                    if (!currentSpanLinks.Remove(link))
                    {
                        // 未找到预期的跨度链接，抛出异常
                        throw new InvalidOperationException($"Couldn't find expected link from span {span.SpanId} to span {link.SpanId}.");
                    }
                }
            }
        }

        // 检查是否有孤立的跨度链接
        if (currentSpanLinks.Count > 0)
        {
            var sb = new StringBuilder();
            sb.AppendLine(CultureInfo.InvariantCulture, $"There are {currentSpanLinks.Count} orphaned span links.");
            foreach (var link in currentSpanLinks)
            {
                sb.AppendLine(CultureInfo.InvariantCulture, $"\tSource span ID: {link.SourceSpanId}, Target span ID: {link.SpanId}");
            }

            // 存在孤立的跨度链接，抛出异常
            throw new InvalidOperationException(sb.ToString());
        }
    }

    /// <summary>
    /// 创建跨度条目。
    /// </summary>
    /// <param name="applicationView">应用程序视图。</param>
    /// <param name="span">原始跨度对象。</param>
    /// <param name="trace">跟踪条目。</param>
    /// <param name="scope">作用域对象。</param>
    /// <param name="context">Otlp上下文对象。</param>
    /// <returns>创建的跨度条目。</returns>
    private static OtlpSpan CreateSpan(OtlpApplicationView applicationView, Span span, OtlpTrace trace, OtlpScope scope, OtlpContext context)
    {
        // 获取跨度ID
        var id = span.SpanId?.ToHexString();
        if (id is null)
        {
            // 跨度必须有ID，否则抛出异常
            throw new ArgumentException("Span has no SpanId");
        }

        // 创建跨度事件列表
        var events = new List<OtlpSpanEvent>();

        // 创建跨度链接列表
        var links = new List<OtlpSpanLink>();
        foreach (var e in span.Links)
        {
            links.Add(new OtlpSpanLink
            {
                SourceSpanId = id,
                SourceTraceId = trace.TraceId,
                TraceState = e.TraceState,
                SpanId = e.SpanId.ToHexString(),
                TraceId = e.TraceId.ToHexString(),
                Attributes = e.Attributes.ToKeyValuePairs(context)
            });
        }

        // 创建新的跨度条目
        var newSpan = new OtlpSpan(applicationView, trace, scope)
        {
            SpanId = id,
            ParentSpanId = span.ParentSpanId?.ToHexString(),
            Name = span.Name,
            Kind = ConvertSpanKind(span.Kind),
            StartTime = OtlpHelpers.UnixNanoSecondsToDateTime(span.StartTimeUnixNano),
            EndTime = OtlpHelpers.UnixNanoSecondsToDateTime(span.EndTimeUnixNano),
            Status = ConvertStatus(span.Status),
            StatusMessage = span.Status?.Message,
            Attributes = span.Attributes.ToKeyValuePairs(context),
            State = span.TraceState,
            Events = events,
            Links = links,
            BackLinks = new()
        };

        // 添加跨度事件
        foreach (var e in span.Events.OrderBy(e => e.TimeUnixNano))
        {
            events.Add(new OtlpSpanEvent(newSpan)
            {
                InternalId = Guid.NewGuid(),
                Name = e.Name,
                Time = OtlpHelpers.UnixNanoSecondsToDateTime(e.TimeUnixNano),
                Attributes = e.Attributes.ToKeyValuePairs(context)
            });

            if (events.Count >= context.Options.MaxSpanEventCount)
            {
                break;
            }
        }
        return newSpan;
    }

    /// <summary>
    /// 获取指定应用程序的仪器摘要列表。
    /// </summary>
    /// <param name="key">应用程序键。</param>
    /// <returns>仪器摘要列表。</returns>
    public List<OtlpInstrumentSummary> GetInstrumentsSummaries(ApplicationKey key)
    {
        // 获取匹配应用程序键的应用程序列表
        var applications = GetApplications(key);
        if (applications.Count == 0)
        {
            // 如果没有匹配的应用程序，返回空列表
            return new List<OtlpInstrumentSummary>();
        }
        else if (applications.Count == 1)
        {
            // 如果只有一个匹配的应用程序，返回该应用程序的仪器摘要列表
            return applications[0].GetInstrumentsSummary();
        }
        else
        {
            // 如果有多个匹配的应用程序，合并并去重仪器摘要列表
            var allApplicationSummaries = applications
               .SelectMany(a => a.GetInstrumentsSummary())
               .DistinctBy(s => s.GetKey())
               .ToList();

            return allApplicationSummaries;
        }

    }

    /// <summary>
    /// 根据请求获取仪器数据。
    /// </summary>
    /// <param name="request">获取仪器数据的请求，包含应用程序键、仪表名称、仪器名称、开始时间和结束时间等信息。</param>
    /// <returns>仪器数据对象，如果未找到则返回null。</returns>
    public OtlpInstrumentData? GetInstrument(GetInstrumentRequest request)
    {
        // 获取匹配应用程序键的应用程序列表
        var applications = GetApplications(request.ApplicationKey);
        // 获取每个应用程序的仪器列表
        var instruments = applications
           .Select(a => a.GetInstrument(request.MeterName, request.InstrumentName, request.StartTime, request.EndTime))
           .OfType<OtlpInstrument>()
           .ToList();

        if (instruments.Count == 0)
        {
            // 如果没有找到仪器，返回null
            return null;
        }
        else if (instruments.Count == 1)
        {
            // 如果只有一个仪器，返回该仪器的数据
            var instrument = instruments[0];
            return new OtlpInstrumentData
            {
                Summary = instrument.Summary,
                KnownAttributeValues = instrument.KnownAttributeValues,
                Dimensions = instrument.Dimensions.Values.ToList(),
                HasOverflow = instrument.HasOverflow
            };
        }
        else
        {
            // 如果有多个仪器，合并仪器数据
            var allDimensions = new List<DimensionScope>();
            var allKnownAttributes = new Dictionary<string, List<string?>>();
            var hasOverflow = false;

            foreach (var instrument in instruments)
            {
                allDimensions.AddRange(instrument.Dimensions.Values);

                foreach (var knownAttributeValues in instrument.KnownAttributeValues)
                {
                    ref var values = ref CollectionsMarshal.GetValueRefOrAddDefault(allKnownAttributes, knownAttributeValues.Key, out _);
                    if (values != null)
                    {
                        values = values.Union(knownAttributeValues.Value).ToList();
                    }
                    else
                    {
                        values = knownAttributeValues.Value.ToList();
                    }
                }

                hasOverflow = hasOverflow || instrument.HasOverflow;
            }

            return new OtlpInstrumentData
            {
                Summary = instruments[0].Summary,
                Dimensions = allDimensions,
                KnownAttributeValues = allKnownAttributes,
                HasOverflow = hasOverflow
            };
        }
    }
}